home *** CD-ROM | disk | FTP | other *** search
/ Aminet 23 / Aminet 23 (1998)(GTI - Schatztruhe)[!][Feb 1998].iso / Aminet / misc / emu / amiSPIMsrc.lha / cl-tlb.c < prev    next >
C/C++ Source or Header  |  1992-11-06  |  6KB  |  323 lines

  1. /* SPIM S20 MIPS Cycle Level simulator.
  2.    Definitions for the SPIM S20 Cycle Level Simulator (SPIM-CL).
  3.    Copyright (C) 1991-1992 by Anne Rogers (amr@cs.princeton.edu) and
  4.    Scott Rosenberg (scottr@cs.princeton.edu)
  5.    ALL RIGHTS RESERVED.
  6.  
  7.    SPIM-CL is distributed under the following conditions:
  8.  
  9.      You may make copies of SPIM-CL for your own use and modify those copies.
  10.  
  11.      All copies of SPIM-CL must retain our names and copyright notice.
  12.  
  13.      You may not sell SPIM-CL or distributed SPIM-CL in conjunction with a
  14.      commerical product or service without the expressed written consent of
  15.      Anne Rogers.
  16.  
  17.    THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  18.    IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  19.    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  20.    PURPOSE.
  21. */
  22.  
  23. #include "spim.h"
  24. #include "inst.h"
  25. #include "reg.h"
  26. #include "mem.h"
  27. #include "mips-syscall.h"
  28. #include "cl-mem.h"
  29. #include "cl-tlb.h"
  30.  
  31.  
  32. struct tlb_entry {
  33.  unsigned int upper, lower;
  34. };
  35.  
  36.  
  37. /* Exported Variables: */
  38.  
  39. int tlb_on;            /* !0 -> tlb handling is on */
  40.  
  41.  
  42. /* Local Functions: */
  43. #ifdef __STDC__
  44. unsigned int find_page (unsigned int vpn);
  45. #else
  46. unsigned int find_page ();
  47. #endif
  48.  
  49.  
  50. #define TLB_SIZE 64        /* tlb size */
  51. #define PT_INCR 100        /* increment size for external page table */
  52. #define tlb_VPN(i) (((TLB[i].upper) >> 12) & 0xfffff)
  53. #define tlb_PID(i) (((TLB[i].upper) >> 6) & (0x3f))
  54. #define tlb_PFN(i) (((TLB[i].lower) >> 12) & (0xfffff))
  55. #define tlb_N(i) (((TLB[i].lower) >> 11) & 0x1)
  56. #define tlb_D(i) (((TLB[i].lower) >> 10) & 0x1)
  57. #define tlb_V(i) (((TLB[i].lower) >> 9) & 0x1)
  58. #define tlb_G(i) (((TLB[i].lower) >> 8) & 0x1)
  59.  
  60. #define tlb_u_update(i, VPN, PID)          \
  61. { TLB[i].upper = ((VPN << 12) | ((PID & 0x3f) << 6)); }
  62.  
  63. #define tlb_l_update(i, PFN, N, D, V, G)   \
  64. { TLB[i].lower = ((PFN << 12) | (N << 11) | (D << 10) | (V << 9) | (G << 1)); }
  65.  
  66. #define tbl_update(i, VPN, PID, PFN, N, D, V, G)  \
  67. { tlb_u_update(i, VPN, PID);                      \
  68.   tlb_l_update(i, PFN, N, D, V, G);               \
  69. }
  70.  
  71.  
  72. /* local variables */
  73.  
  74. static struct tlb_entry TLB[TLB_SIZE];    /* tlb's register-based page table */
  75. static struct tlb_entry *PT = NULL;    /* external page table information */
  76. static int pt_high;
  77. static int pt_size;
  78.  
  79.  
  80.  
  81. #ifdef __STDC__
  82. void
  83. tlb_init (void)
  84. #else
  85. void
  86. tlb_init ()
  87. #endif
  88. {
  89.   int i;
  90.  
  91.   for (i=1; i < TLB_SIZE; i++) {
  92.     TLB[i].upper = 0;
  93.     TLB[i].lower = 0;
  94.   }
  95.  
  96.   Random = 63 << 8;
  97.  
  98.   free (PT);
  99.   PT = NULL;
  100.   pt_high = 0;
  101.   pt_size = 0;
  102. }
  103.  
  104.  
  105. /* Virtual Address Translation  -- See Kane Ch. 4*/
  106. /* VPN is in the low order 20 bits of the variable vpn */
  107. /* PID is in the low order 6 bits of the variable pid */
  108. #ifdef __STDC__
  109. int
  110. tlb_vat (mem_addr addr, unsigned int pid, int l_or_s, mem_addr *paddr)
  111. #else
  112. int
  113. tlb_vat(addr, pid, l_or_s, paddr)
  114.   mem_addr addr, *paddr;
  115.   unsigned int pid;
  116.   int l_or_s;
  117. #endif
  118. {
  119.   int i, msb;
  120.   mem_addr temp_badvaddr;
  121.   unsigned int vpn;
  122.  
  123.   if (!tlb_on) {
  124.     *paddr = addr;
  125.     return CACHEABLE;
  126.   }
  127.  
  128.   vpn = addr >> 12;
  129.   temp_badvaddr = BadVAddr;
  130.   BadVAddr = addr & 0xfffff000;
  131.  
  132.   msb = (vpn >> 19) & 0x1;
  133.  
  134.  
  135.   if (msb & (Status_Reg & 0x2))
  136.     return ((l_or_s) ? ADDRL_EXCPT : ADDRS_EXCPT);
  137.  
  138.  
  139.   for (i=0; i < TLB_SIZE; i++) {
  140.     if (tlb_VPN(i) == vpn)
  141.       break;
  142.   }
  143.  
  144.   if (i >= TLB_SIZE)  {
  145.     return ((l_or_s) ? TLBL_EXCPT : TLBS_EXCPT);
  146.   }
  147.  
  148.  
  149.   if ((!tlb_G(i)) && (tlb_PID(i) != pid))
  150.     return ((l_or_s) ? TLBL_EXCPT : TLBS_EXCPT);
  151.  
  152.  
  153.   if (!(tlb_V(i))) {
  154.     return ((l_or_s) ? TLBL_EXCPT : TLBS_EXCPT);
  155.   }
  156.  
  157.   if (!(tlb_D(i)) && !(l_or_s)) {
  158.     return (MOD_EXCPT);
  159.   }
  160.  
  161.   BadVAddr = temp_badvaddr;
  162.   *paddr = (tlb_PFN(i) << 12) | (addr & 0xfff);
  163.  
  164.   return ((tlb_N(i)) ? CACHEABLE : NOT_CACHEABLE);
  165. }
  166.  
  167.  
  168.  
  169.  
  170. /* TLB Probe */
  171.  
  172. #ifdef __STDC__
  173. void
  174. tlbp (void)
  175. #else
  176. void
  177. tlbp ()
  178. #endif
  179. {
  180.   int vpn, pid;
  181.   int i;
  182.  
  183.   vpn = EntryHI >> 12;
  184.   pid = (EntryHI >> 6) & 0x3f;
  185.  
  186.   for (i=0; i < TLB_SIZE; i++)
  187.     if (tlb_VPN(i) == vpn)
  188.       break;
  189.  
  190.   if ((i == TLB_SIZE) || (tlb_PID(i) != pid))
  191.     /* no match found */
  192.     Index = (1 << 31);
  193.   else
  194.     Index = (i << 8);
  195. }
  196.  
  197.  
  198. /* TLB Read */
  199.  
  200. #ifdef __STDC__
  201. void
  202. tlbr (void)
  203. #else
  204. void
  205. tlbr ()
  206. #endif
  207. {
  208.   int index;
  209.  
  210.   index = (Index >> 8) & 0x3f;
  211.   EntryHI = TLB[index].upper;
  212.   EntryLO = TLB[index].lower;
  213. }
  214.  
  215.  
  216. /* TLB Write Indexed */
  217.  
  218. #ifdef __STDC__
  219. void
  220. tlbwi (void)
  221. #else
  222. void
  223. tlbwi ()
  224. #endif
  225. {
  226.   int index;
  227.  
  228.   index = (Index >> 8) & 0x3f;
  229.   TLB[index].upper = EntryHI;
  230.   TLB[index].lower = EntryLO;
  231. }
  232.  
  233.  
  234. /* TLB Write Random */
  235.  
  236. #ifdef __STDC__
  237. void
  238. tlbwr (void)
  239. #else
  240. void
  241. tlbwr ()
  242. #endif
  243. {
  244.   int index;
  245.  
  246.   index = (Random >> 8) & 0x3f;
  247.   TLB[index].upper = EntryHI;
  248.   TLB[index].lower = EntryLO;
  249. }
  250.  
  251.  
  252.  
  253. /* Service a TLB miss */
  254.  
  255. #ifdef __STDC__
  256. void
  257. tlb_service (unsigned int pid, int l_or_s)
  258. #else
  259. void
  260. tlb_service (pid, l_or_s)
  261.   unsigned int pid;
  262.   int l_or_s;
  263. #endif
  264. {
  265.   unsigned int vpn, pfn;
  266.  
  267.   vpn = (BadVAddr >> 12) & 0xfffff;
  268.   pfn = find_page(vpn);
  269.   EntryHI = ((vpn << 12) | (pid << 6));
  270.   EntryLO = ((pfn << 12) | (1 << 11) | (!l_or_s << 10) | (1 << 9));
  271.  
  272.   tlbp();
  273.   if (Index >> 31)
  274.     /* No match found */
  275.     tlbwr();
  276.   else
  277.     tlbwi();
  278.  
  279. }
  280.  
  281.  
  282. #ifdef __STDC__
  283. unsigned int
  284. find_page (unsigned int vpn)
  285. #else
  286. unsigned int find_page (vpn)
  287.   unsigned int vpn;
  288. #endif
  289. {
  290.   int i;
  291.  
  292.   for (i = 0; i < pt_high; i++)
  293.     if ((((PT[i].upper >> 12) & 0xfffff) == vpn) &&
  294.     ((PT[i].lower >> 9) & 0x1))
  295.       {
  296.     return i;
  297.       }
  298.  
  299.   if (pt_high >= pt_size) {
  300.     PT = (struct tlb_entry *)
  301.       realloc(PT, (pt_size + PT_INCR) * sizeof(struct tlb_entry));
  302.     if (PT == NULL) printf("Realloc in find_page failed -- %d\n",
  303.                (pt_size+PT_INCR) * sizeof(struct tlb_entry));
  304.  
  305.     /* initialize entries in new_space, that is, make them invalid. */
  306.     for (i=pt_high; i < pt_size; i++)
  307.       PT[i].lower = 0;
  308.  
  309.     pt_size += PT_INCR;
  310.   }
  311.  
  312.   PT[pt_high].upper = vpn << 12;
  313.   PT[pt_high].lower = 1 << 9;
  314.   return pt_high++;
  315.  
  316. }
  317.  
  318.  
  319.  
  320.  
  321.  
  322.  
  323.